home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_093 / microemacs / source / src.arc / buffer.c < prev    next >
C/C++ Source or Header  |  1987-08-16  |  16KB  |  529 lines

  1. /*
  2.  * Buffer management.
  3.  * Some of the functions are internal,
  4.  * and some are actually attached to user
  5.  * keys. Like everyone else, they set hints
  6.  * for the display system.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. /*
  13.  * Attach a buffer to a window. The
  14.  * values of dot and mark come from the buffer
  15.  * if the use count is 0. Otherwise, they come
  16.  * from some other window.
  17.  */
  18. usebuffer(f, n)
  19. {
  20.         register BUFFER *bp;
  21.         register int    s;
  22.         char            bufn[NBUFN];
  23.  
  24.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  25.                 return (s);
  26.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  27.                 return (FALSE);
  28.     return(swbuffer(bp));
  29. }
  30.  
  31. nextbuffer(f, n)    /* switch to the next buffer in the buffer list */
  32.  
  33. int f, n;    /* default flag, numeric argument */
  34. {
  35.     register BUFFER *bp;    /* eligable buffer to switch to*/
  36.     register BUFFER *bbp;    /* eligable buffer to switch to*/
  37.  
  38.     /* make sure the arg is legit */
  39.     if (f == FALSE)
  40.         n = 1;
  41.     if (n < 1)
  42.         return(FALSE);
  43.  
  44.     bbp = curbp;
  45.     while (n-- > 0) {
  46.         /* advance to the next buffer */
  47.         bp = bbp->b_bufp;
  48.  
  49.         /* cycle through the buffers to find an eligable one */
  50.         while (bp == NULL || bp->b_flag & BFINVS) {
  51.             if (bp == NULL)
  52.                 bp = bheadp;
  53.             else
  54.                 bp = bp->b_bufp;
  55.  
  56.             /* don't get caught in an infinite loop! */
  57.             if (bp == bbp)
  58.                 return(FALSE);
  59.  
  60.         }        
  61.  
  62.         bbp = bp;
  63.     }
  64.  
  65.     return(swbuffer(bp));
  66. }
  67.  
  68. swbuffer(bp)    /* make buffer BP current */
  69.  
  70. BUFFER *bp;
  71.  
  72. {
  73.         register WINDOW *wp;
  74.  
  75.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  76.                 curbp->b_dotp  = curwp->w_dotp;
  77.                 curbp->b_doto  = curwp->w_doto;
  78.                 curbp->b_markp = curwp->w_markp;
  79.                 curbp->b_marko = curwp->w_marko;
  80.         }
  81.         curbp = bp;                             /* Switch.              */
  82.     if (curbp->b_active != TRUE) {        /* buffer not active yet*/
  83.         /* read it in and activate it */
  84.         readin(curbp->b_fname, TRUE);
  85.         curbp->b_dotp = lforw(curbp->b_linep);
  86.         curbp->b_doto = 0;
  87.         curbp->b_active = TRUE;
  88.     }
  89.         curwp->w_bufp  = bp;
  90.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  91.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  92.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  93.                 curwp->w_dotp  = bp->b_dotp;
  94.                 curwp->w_doto  = bp->b_doto;
  95.                 curwp->w_markp = bp->b_markp;
  96.                 curwp->w_marko = bp->b_marko;
  97.                 return (TRUE);
  98.         }
  99.         wp = wheadp;                            /* Look for old.        */
  100.         while (wp != NULL) {
  101.                 if (wp!=curwp && wp->w_bufp==bp) {
  102.                         curwp->w_dotp  = wp->w_dotp;
  103.                         curwp->w_doto  = wp->w_doto;
  104.                         curwp->w_markp = wp->w_markp;
  105.                         curwp->w_marko = wp->w_marko;
  106.                         break;
  107.                 }
  108.                 wp = wp->w_wndp;
  109.         }
  110.         return (TRUE);
  111. }
  112.  
  113. /*
  114.  * Dispose of a buffer, by name.
  115.  * Ask for the name. Look it up (don't get too
  116.  * upset if it isn't there at all!). Get quite upset
  117.  * if the buffer is being displayed. Clear the buffer (ask
  118.  * if the buffer has been changed). Then free the header
  119.  * line and the buffer header. Bound to "C-X K".
  120.  */
  121. killbuffer(f, n)
  122.  
  123. {
  124.     register BUFFER *bp;
  125.         register int    s;
  126.         char bufn[NBUFN];
  127.  
  128.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  129.                 return(s);
  130.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  131.                 return (TRUE);
  132.     if(bp->b_flag & BFINVS)        /* Deal with special buffers    */
  133.             return (TRUE);        /* by doing nothing.    */
  134.     return(zotbuf(bp));
  135. }
  136.  
  137. zotbuf(bp)    /* kill the buffer pointed to by bp */
  138.  
  139. register BUFFER *bp;
  140.  
  141. {
  142.         register BUFFER *bp1;
  143.         register BUFFER *bp2;
  144.         register int    s;
  145.  
  146.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  147.                 mlwrite("Buffer is being displayed");
  148.                 return (FALSE);
  149.         }
  150.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  151.                 return (s);
  152.         free((char *) bp->b_linep);             /* Release header line. */
  153.         bp1 = NULL;                             /* Find the header.     */
  154.         bp2 = bheadp;
  155.         while (bp2 != bp) {
  156.                 bp1 = bp2;
  157.                 bp2 = bp2->b_bufp;
  158.         }
  159.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  160.         if (bp1 == NULL)                        /* Unlink it.           */
  161.                 bheadp = bp2;
  162.         else
  163.                 bp1->b_bufp = bp2;
  164.         free((char *) bp);                      /* Release buffer block */
  165.         return (TRUE);
  166. }
  167.  
  168. namebuffer(f,n)        /*    Rename the current buffer    */
  169.  
  170. int f, n;        /* default Flag & Numeric arg */
  171.  
  172. {
  173.     register BUFFER *bp;    /* pointer to scan through all buffers */
  174.     char bufn[NBUFN];    /* buffer to hold buffer name */
  175.  
  176.     /* prompt for and get the new buffer name */
  177. ask:    if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE)
  178.         return(FALSE);
  179.  
  180.     /* and check for duplicates */
  181.     bp = bheadp;
  182.     while (bp != NULL) {
  183.         if (bp != curbp) {
  184.             /* if the names the same */
  185.             if (strcmp(bufn, bp->b_bname) == 0)
  186.                 goto ask;  /* try again */
  187.         }
  188.         bp = bp->b_bufp;    /* onward */
  189.     }
  190.  
  191.     strcpy(curbp->b_bname, bufn);    /* copy buffer name to structure */
  192.     curwp->w_flag |= WFMODE;    /* make mode line replot */
  193.     mlerase();
  194.     return(TRUE);
  195. }
  196.  
  197. /*
  198.     List all of the active buffers.  First update the special
  199.     buffer that holds the list.  Next make sure at least 1
  200.     window is displaying the buffer list, splitting the screen
  201.     if this is what it takes.  Lastly, repaint all of the
  202.     windows that are displaying the list.  Bound to "C-X C-B". 
  203.     A numeric argument forces it to list invisable buffers as
  204.     well.
  205. */
  206.  
  207. listbuffers(f, n)
  208. {
  209.         register WINDOW *wp;
  210.         register BUFFER *bp;
  211.         register int    s;
  212.  
  213.         if ((s=makelist(f)) != TRUE)
  214.                 return (s);
  215.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  216.                 if ((wp=wpopup()) == NULL)
  217.                         return (FALSE);
  218.                 bp = wp->w_bufp;
  219.                 if (--bp->b_nwnd == 0) {
  220.                         bp->b_dotp  = wp->w_dotp;
  221.                         bp->b_doto  = wp->w_doto;
  222.                         bp->b_markp = wp->w_markp;
  223.                         bp->b_marko = wp->w_marko;
  224.                 }
  225.                 wp->w_bufp  = blistp;
  226.                 ++blistp->b_nwnd;
  227.         }
  228.         wp = wheadp;
  229.         while (wp != NULL) {
  230.                 if (wp->w_bufp == blistp) {
  231.                         wp->w_linep = lforw(blistp->b_linep);
  232.                         wp->w_dotp  = lforw(blistp->b_linep);
  233.                         wp->w_doto  = 0;
  234.                         wp->w_markp = NULL;
  235.                         wp->w_marko = 0;
  236.                         wp->w_flag |= WFMODE|WFHARD;
  237.                 }
  238.                 wp = wp->w_wndp;
  239.         }
  240.         return (TRUE);
  241. }
  242.  
  243. /*
  244.  * This routine rebuilds the
  245.  * text in the special secret buffer
  246.  * that holds the buffer list. It is called
  247.  * by the list buffers command. Return TRUE
  248.  * if everything works. Return FALSE if there
  249.  * is an error (if there is no memory). Iflag
  250.  * indecates weather to list hidden buffers.
  251.  */
  252. makelist(iflag)
  253.  
  254. int iflag;    /* list hidden buffer flag */
  255.  
  256. {
  257.         register char   *cp1;
  258.         register char   *cp2;
  259.         register int    c;
  260.         register BUFFER *bp;
  261.         register LINE   *lp;
  262.         register int    s;
  263.     register int    i;
  264.         long nbytes;        /* # of bytes in current buffer */
  265.         char b[7+1];
  266.         char line[128];
  267.  
  268.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  269.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  270.                 return (s);
  271.         strcpy(blistp->b_fname, "");
  272.         if (addline("AC MODES        Size Buffer        File") == FALSE
  273.         ||  addline("-- -----        ---- ------        ----") == FALSE)
  274.                 return (FALSE);
  275.         bp = bheadp;                            /* For all buffers      */
  276.  
  277.     /* build line to report global mode settings */
  278.     cp1 = &line[0];
  279.     *cp1++ = ' ';
  280.     *cp1++ = ' ';
  281.     *cp1++ = ' ';
  282.  
  283.     /* output the mode codes */
  284.     for (i = 0; i < NUMMODES; i++)
  285.         if (gmode & (1 << i))
  286.             *cp1++ = modecode[i];
  287.         else
  288.             *cp1++ = '.';
  289.     strcpy(cp1, "         Global Modes");
  290.     if (addline(line) == FALSE)
  291.         return(FALSE);
  292.  
  293.     /* output the list of buffers */
  294.         while (bp != NULL) {
  295.         /* skip invisable buffers if iflag is false */
  296.                 if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) {
  297.                         bp = bp->b_bufp;
  298.                         continue;
  299.                 }
  300.                 cp1 = &line[0];                 /* Start at left edge   */
  301.  
  302.         /* output status of ACTIVE flag (has the file been read in? */
  303.                 if (bp->b_active == TRUE)    /* "@" if activated       */
  304.                         *cp1++ = '@';
  305.                 else
  306.                         *cp1++ = ' ';
  307.  
  308.         /* output status of changed flag */
  309.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  310.                         *cp1++ = '*';
  311.                 else
  312.                         *cp1++ = ' ';
  313.                 *cp1++ = ' ';                   /* Gap.                 */
  314.  
  315.         /* output the mode codes */
  316.         for (i = 0; i < NUMMODES; i++) {
  317.             if (bp->b_mode & (1 << i))
  318.                 *cp1++ = modecode[i];
  319.             else
  320.                 *cp1++ = '.';
  321.         }
  322.                 *cp1++ = ' ';                   /* Gap.                 */
  323.                 nbytes = 0L;                    /* Count bytes in buf.  */
  324.                 lp = lforw(bp->b_linep);
  325.                 while (lp != bp->b_linep) {
  326.                         nbytes += (long)llength(lp)+1L;
  327.                         lp = lforw(lp);
  328.                 }
  329.                 ltoa(b, 7, nbytes);             /* 6 digit buffer size. */
  330.                 cp2 = &b[0];
  331.                 while ((c = *cp2++) != 0)
  332.                         *cp1++ = c;
  333.                 *cp1++ = ' ';                   /* Gap.                 */
  334.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  335.                 while ((c = *cp2++) != 0)
  336.                         *cp1++ = c;
  337.                 cp2 = &bp->b_fname[0];          /* File name            */
  338.                 if (*cp2 != 0) {
  339.                         while (cp1 < &line[2+1+5+1+6+1+NBUFN])
  340.                                 *cp1++ = ' ';
  341.                         while ((c = *cp2++) != 0) {
  342.                                 if (cp1 < &line[128-1])
  343.                                         *cp1++ = c;
  344.                         }
  345.                 }
  346.                 *cp1 = 0;                       /* Add to the buffer.   */
  347.                 if (addline(line) == FALSE)
  348.                         return (FALSE);
  349.                 bp = bp->b_bufp;
  350.         }
  351.         return (TRUE);                          /* All done             */
  352. }
  353.  
  354. ltoa(buf, width, num)
  355.  
  356. char   buf[];
  357. int    width;
  358. long   num;
  359.  
  360. {
  361.         buf[width] = 0;                         /* End of string.       */
  362.         while (num >= 10) {                     /* Conditional digits.  */
  363.                 buf[--width] = (int)(num%10L) + '0';
  364.                 num /= 10L;
  365.         }
  366.         buf[--width] = (int)num + '0';          /* Always 1 digit.      */
  367.         while (width != 0)                      /* Pad with blanks.     */
  368.                 buf[--width] = ' ';
  369. }
  370.  
  371. /*
  372.  * The argument "text" points to
  373.  * a string. Append this line to the
  374.  * buffer list buffer. Handcraft the EOL
  375.  * on the end. Return TRUE if it worked and
  376.  * FALSE if you ran out of room.
  377.  */
  378. addline(text)
  379. char    *text;
  380. {
  381.         register LINE   *lp;
  382.         register int    i;
  383.         register int    ntext;
  384.  
  385.         ntext = strlen(text);
  386.         if ((lp=lalloc(ntext)) == NULL)
  387.                 return (FALSE);
  388.         for (i=0; i<ntext; ++i)
  389.                 lputc(lp, i, text[i]);
  390.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  391.         lp->l_bp = blistp->b_linep->l_bp;
  392.         blistp->b_linep->l_bp = lp;
  393.         lp->l_fp = blistp->b_linep;
  394.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  395.                 blistp->b_dotp = lp;            /* move it to new line  */
  396.         return (TRUE);
  397. }
  398.  
  399. /*
  400.  * Look through the list of
  401.  * buffers. Return TRUE if there
  402.  * are any changed buffers. Buffers
  403.  * that hold magic internal stuff are
  404.  * not considered; who cares if the
  405.  * list of buffer names is hacked.
  406.  * Return FALSE if no buffers
  407.  * have been changed.
  408.  */
  409. anycb()
  410. {
  411.         register BUFFER *bp;
  412.  
  413.         bp = bheadp;
  414.         while (bp != NULL) {
  415.                 if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0)
  416.                         return (TRUE);
  417.                 bp = bp->b_bufp;
  418.         }
  419.         return (FALSE);
  420. }
  421.  
  422. /*
  423.  * Find a buffer, by name. Return a pointer
  424.  * to the BUFFER structure associated with it.
  425.  * If the buffer is not found
  426.  * and the "cflag" is TRUE, create it. The "bflag" is
  427.  * the settings for the flags in in buffer.
  428.  */
  429. BUFFER  *
  430. bfind(bname, cflag, bflag)
  431. register char   *bname;
  432. {
  433.         register BUFFER *bp;
  434.     register BUFFER *sb;    /* buffer to insert after */
  435.         register LINE   *lp;
  436.     char *malloc();
  437.  
  438.         bp = bheadp;
  439.         while (bp != NULL) {
  440.                 if (strcmp(bname, bp->b_bname) == 0)
  441.                         return (bp);
  442.                 bp = bp->b_bufp;
  443.         }
  444.         if (cflag != FALSE) {
  445.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  446.                         return (NULL);
  447.                 if ((lp=lalloc(0)) == NULL) {
  448.                         free((char *) bp);
  449.                         return (NULL);
  450.                 }
  451.         /* find the place in the list to insert this buffer */
  452.         if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) {
  453.             /* insert at the beginning */
  454.                     bp->b_bufp = bheadp;
  455.                     bheadp = bp;
  456.             } else {
  457.             sb = bheadp;
  458.             while (sb->b_bufp != NULL) {
  459.                 if (strcmp(sb->b_bufp->b_bname, bname) > 0)
  460.                     break;
  461.                 sb = sb->b_bufp;
  462.             }
  463.  
  464.             /* and insert it */
  465.                    bp->b_bufp = sb->b_bufp;
  466.                 sb->b_bufp = bp;
  467.                }
  468.  
  469.         /* and set up the other buffer fields */
  470.         bp->b_active = TRUE;
  471.                 bp->b_dotp  = lp;
  472.                 bp->b_doto  = 0;
  473.                 bp->b_markp = NULL;
  474.                 bp->b_marko = 0;
  475.                 bp->b_flag  = bflag;
  476.         bp->b_mode  = gmode;
  477.                 bp->b_nwnd  = 0;
  478.                 bp->b_linep = lp;
  479.                 strcpy(bp->b_fname, "");
  480.                 strcpy(bp->b_bname, bname);
  481. #if    CRYPT
  482.         bp->b_key[0] = 0;
  483. #endif
  484.                 lp->l_fp = lp;
  485.                 lp->l_bp = lp;
  486.         }
  487.         return (bp);
  488. }
  489.  
  490. /*
  491.  * This routine blows away all of the text
  492.  * in a buffer. If the buffer is marked as changed
  493.  * then we ask if it is ok to blow it away; this is
  494.  * to save the user the grief of losing text. The
  495.  * window chain is nearly always wrong if this gets
  496.  * called; the caller must arrange for the updates
  497.  * that are required. Return TRUE if everything
  498.  * looks good.
  499.  */
  500. bclear(bp)
  501. register BUFFER *bp;
  502. {
  503.         register LINE   *lp;
  504.         register int    s;
  505.  
  506.         if ((bp->b_flag&BFINVS) == 0            /* Not scratch buffer.  */
  507.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  508.         && (s=mlyesno("Discard changes")) != TRUE)
  509.                 return (s);
  510.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  511.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  512.                 lfree(lp);
  513.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  514.         bp->b_doto  = 0;
  515.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  516.         bp->b_marko = 0;
  517.         return (TRUE);
  518. }
  519.  
  520. unmark(f, n)    /* unmark the current buffers change flag */
  521.  
  522. int f, n;    /* unused command arguments */
  523.  
  524. {
  525.     curbp->b_flag &= ~BFCHG;
  526.     curwp->w_flag |= WFMODE;
  527.     return(TRUE);
  528. }
  529.